package com.yanfan.ccapicode.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.yanfan.ccapicode.bean.dto.RequestTokenDTO;
import com.yanfan.ccapicode.bean.info.AccessTokenInfo;
import com.yanfan.ccapicode.bean.info.ThirdPartyCloudConfigInfo;
import com.yanfan.ccapicode.bean.vo.AccessTokenVO;
import com.yanfan.ccapicode.mangaer.AccessTokenManager;
import com.yanfan.ccapicode.mangaer.ClientOauthManager;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * :)
 *
 */
@Service
public class OAuthServiceImpl implements OAuthService {

    public static final String USER_ID = "userId";

    private final AccessTokenManager accessTokenManager;
    private final ThirdPartyConfigService thirdPartyConfigService;
    private final ClientOauthManager clientOauthManager;

    public OAuthServiceImpl(AccessTokenManager accessTokenManager, ThirdPartyConfigService thirdPartyConfigService, ClientOauthManager clientOauthManager) {
        this.accessTokenManager = accessTokenManager;
        this.thirdPartyConfigService = thirdPartyConfigService;
        this.clientOauthManager = clientOauthManager;
    }

    @SneakyThrows
    @Override
    public String generateOAuthCode(String clientId, HttpServletRequest request, HttpServletResponse response) {
        String userId = request.getParameter(USER_ID);
        if (StrUtil.isBlank(userId)) {
            userId = request.getHeader(USER_ID);
        }

        ThirdPartyCloudConfigInfo config = thirdPartyConfigService.getConfig(clientId);

        switch (config.getThirdPartyCloud()) {
            case BAIDU: {
                if (StrUtil.isBlank(userId)) {
                    userId = request.getParameter("dueros_uid");
                }
                String code = accessTokenManager.generateOAuthCode(clientId, userId, config);
                Map<String, String> query = new LinkedHashMap<>();
                String redirectUri = request.getParameter("redirect_uri");
                String state = request.getParameter("state");
                query.put("code", code);
                query.put("state", state);
                response.sendRedirect(redirectUri + "?" + HttpUtil.toParams(query));
                return null;
            }
            default: {
                return accessTokenManager.generateOAuthCode(clientId, userId, config);
            }
        }

    }

    @Override
    public AccessTokenVO generateAccessTokenByCode(String code, String clientId) {
        AccessTokenInfo accessTokenEntity = accessTokenManager.generateAccessTokenByCode(code, clientId);
        return AccessTokenVO
                .builder()
                .access_token(accessTokenEntity.getAccessToken())
                .refresh_token(accessTokenEntity.getRefreshToken())
                .expires_in(accessTokenEntity.getExpiresIn())
                .token_type(accessTokenEntity.getTokenType())
                .build();
    }

    @Override
    public AccessTokenVO generateAccessTokenByRefreshToken(String refreshToken, String clientId) {
        AccessTokenInfo accessTokenEntity = accessTokenManager.generateAccessTokenByRefreshToken(refreshToken, clientId);
        return AccessTokenVO
                .builder()
                .access_token(accessTokenEntity.getAccessToken())
                .refresh_token(accessTokenEntity.getRefreshToken())
                .expires_in(accessTokenEntity.getExpiresIn())
                .token_type(accessTokenEntity.getTokenType())
                .build();
    }


    @Override
    public void requestExchangeAccessToken(RequestTokenDTO requestToken) {

        ThirdPartyCloudConfigInfo config = thirdPartyConfigService.getConfig(requestToken.getClientId());
        if (ObjectUtil.isNull(config)) {
            //TODO 配置不存在
//            throw new AccessTokenException("access token invalid");
        }
        if (!requestToken.getApiId().equals(config.getApiId())) {
            //TODO 越权访问
//            throw new AccessTokenException("access token invalid");
        }

        clientOauthManager.requestExchangeAccessToken(requestToken);
    }
}
